package com.tansun.easycare.rule.ruleexcute.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.tansun.easycare.rule.codeblock.service.RuleCodeblockService;
import com.tansun.easycare.rule.common.service.DataBomService;
import com.tansun.easycare.rule.exception.BizException;
import com.tansun.easycare.rule.ruleexcute.model.RuleExecuteVO;
import com.tansun.easycare.rule.ruleexcute.service.RuleExcuteService;
import com.tansun.easycare.rule.ruleflow.service.RuleFlowService;
import com.tansun.easycare.rule.rulelog.entity.RuleLogs;
import com.tansun.easycare.rule.ruletest.model.RuleItem;
import com.tansun.easycare.rule.ruletest.model.TestDataModeVO;
import com.tansun.easycare.rule.ruletest.model.TestDatasetVO;
import com.tansun.easycare.rule.ruletest.service.RuleTestService;
import com.tansun.easycare.rule.ruleversion.entity.RuleVersioninfo;
import com.tansun.easycare.rule.utils.DroolsExcuteDrlUtils;
import com.tansun.easycare.rule.utils.RuleMapAndJsonUtils;
import com.tansun.rule.common.RuleModelTypeEnum;
import com.tansun.rule.utils.DroolsRuleLog;
import com.tansun.rule.utils.MClass;
import com.tansun.rule.utils.MField;
import com.tansun.rule.utils.MathHelper;
import com.tansun.rule.utils.RuleBomMapJsonConvert;
import com.tansun.rule.utils.RuleBomMapXmlConvert;
import com.tansun.ruledata.data.service.RuleResourceLoadService;

@Service
public class RuleExcuteServiceImpl implements RuleExcuteService {

    @Autowired
    private DataBomService dataBomService;
    @Autowired
    private RuleFlowService ruleFlowService;

    @Autowired
    private RuleTestService ruleTestService;

    @Autowired
    private RuleCodeblockService ruleCodeblockService;

    @Override
    public String getXmlForTest(String type, String projectCode) throws Exception {

        Map<String, MClass> metaMap = dataBomService.findMapClass(projectCode);

        RuleBomMapXmlConvert ruleBomMapXmlConvert = new RuleBomMapXmlConvert();
        Map<String, Object> insertMap = ruleBomMapXmlConvert.buildMap(metaMap, true);
        if ("xml".equals(type)) {
            return RuleBomMapXmlConvert.bom2xml(insertMap, metaMap, true);
        } else {
            return RuleBomMapJsonConvert.bom2Json(insertMap, metaMap);
        }
    }

    @Override
    public String getRuleFlowXmlForTest(RuleExecuteVO ruleExecute) throws BizException {

                TestDataModeVO testDataModeVO = this.ruleTestService.findDataModeVO(ruleExecute.getProjectCode(), ruleExecute.getCode(), ruleExecute.getModelType(), ruleExecute.getVersion());
                //对象封装
                Map<String, MClass> resultMap = new HashMap<String, MClass>();
                List<TestDatasetVO> dataList = new ArrayList<TestDatasetVO>();
                if (testDataModeVO.getInputDataModel() != null && testDataModeVO.getInputDataModel().size() > 0) {
                	dataList.addAll(testDataModeVO.getInputDataModel());
                }
                if (testDataModeVO.getThenDataModel() != null && testDataModeVO.getThenDataModel().size() > 0) {
                	dataList.addAll(testDataModeVO.getThenDataModel());
                }
                if (dataList.size() > 0) {
                    for (TestDatasetVO datamodel : dataList) {
                    	MClass mClass = null;
                    	if(resultMap.containsKey(datamodel.getName())) {
                    		mClass = resultMap.get(datamodel.getName());
                    	}else {
                    		mClass = new MClass();
                    	}
                        mClass.setName(datamodel.getName());
                        mClass.setChzn(datamodel.getChzn());
                        mClass.setParamType(datamodel.getParamType() == null ? "ALL" : datamodel.getParamType());

                        resultMap.put(datamodel.getName(), mClass);
                        List<RuleItem> attrList = datamodel.getAttrList();
                        if (attrList != null && attrList.size() > 0) {
                            for (RuleItem attr : attrList) {
                                MField mField = new MField();
                                mField.setId(attr.getId());
                                mField.setChzn(attr.getNamecn());
                                mField.setDefaultValue(attr.getDefaultValue());
                                mField.setDomain(attr.getDomain());
                                mField.setName(attr.getNameen());
                                mField.setPattern(attr.getPattern());
                                mField.setType(attr.getDataType());
                                mField.setIsDerives(attr.getIsDerives());
                                mField.setIsCollections(attr.getIsCollections());
                                mField.setCollection(attr.getCollection());
                                mClass.getmFieldNames().add(attr.getNameen());
                                mClass.getFieldMap().put(attr.getNameen(), mField);
                            }
                        }

                    }
                }
                RuleBomMapXmlConvert ruleBomMapXmlConvert = new RuleBomMapXmlConvert();
                Map<String, Object> insertMap = ruleBomMapXmlConvert.buildMap(resultMap, true);

               return RuleBomMapJsonConvert.bom2Json(insertMap, resultMap);
    }


    @Override
    public String excuteDrl(String xml, String[] contentDrl, String bpmnContent, String type, Map<String, MClass> metaMap, String agendaGroup) throws BizException {
        Map<String, Object> insertMap = null;
        try {
            if ("xml".equals(type)) {
                insertMap = RuleBomMapXmlConvert.xml2bom(xml, metaMap);
            } else {
                insertMap = RuleBomMapJsonConvert.json2bom(xml, metaMap);
            }

            DroolsExcuteDrlUtils dedfu = new DroolsExcuteDrlUtils();
            dedfu.excuteDrl(insertMap, contentDrl, metaMap, agendaGroup, new String[]{bpmnContent});

            DroolsRuleLog droolsRuleLog = dedfu.getDroolsRuleLog();
            List<Map<String, Object>> list = droolsRuleLog.getLogs();
            for (Map<String, Object> map : list) {
                System.out.println(map.get("group") + ":" + map.get("name"));
            }
            if ("xml".equals(type)) {
                return RuleBomMapXmlConvert.bom2xml(insertMap, metaMap, true);
            } else {
                return RuleBomMapJsonConvert.bom2Json(insertMap, metaMap);
            }
        } catch (Exception e) {
            throw new BizException(e, "");
        }
    }
    @Autowired
    RuleResourceLoadService ruleResourceLoadService;
    @Override
    public String excuteDrl(String xml, String ruleflowInfo, String type, String projectCode,String bcm,String modelType) throws Exception {
        if (StringUtils.isEmpty(ruleflowInfo)) {
            return null;
        }
        Map<String, MClass> metaMap = dataBomService.findMapClass(projectCode);

        Map<String, Object> insertMap = null;
        Map<String,Object> businessInputMap = JSON.parseObject(xml, Map.class);
        if ("xml".equals(type)) {
            insertMap = RuleBomMapXmlConvert.xml2bom(xml, metaMap);
            //insertMap = RuleMapAndXmlUtils.xmlCoverMap(xml,metaMap);
        } else {
            if("0".equals(bcm)){
                insertMap = RuleBomMapJsonConvert.json2bom(xml, metaMap);
            }else{
                //20200102 ljt
                insertMap = RuleMapAndJsonUtils.jsonCoverMap(businessInputMap,metaMap);
                System.out.println("json入参转化为对应的insertMap为："+insertMap);
            }

        }
        String[] ruleArgs = StringUtils.split(ruleflowInfo, "_");

        List<RuleVersioninfo> vList = this.ruleFlowService.findRuleFlowPublishVersion(projectCode, ruleArgs[0], ruleArgs[1]);
        ruleCodeblockService.addFuncInfo(vList);
//        for (RuleVersioninfo ruleVersioninfo : vList) {
//			if("19".equals(ruleVersioninfo.getModelType())) {
//				ruleVersioninfo.setRuleContent(FileUtils.readFileToString(new File("C:\\d3.txt")));
//			}
//		}
        DroolsExcuteDrlUtils dedfu = new DroolsExcuteDrlUtils();
        dedfu.setProjectCode(projectCode);
        Map<String,String> funcMap  = new  HashMap<>();
        funcMap.put(projectCode,this.ruleCodeblockService.getEffectiveFunc(projectCode));
        dedfu.setFuncMap(funcMap);	
        dedfu.setDrlMap(this.ruleFlowService.findRuleRefeVerByProjectCode(projectCode));
        if (RuleModelTypeEnum.RuleFlow.code.equals(modelType)|| RuleModelTypeEnum.StrategyFlow.code.equals(modelType)) {
          ruleResourceLoadService.loadProjectPmml(projectCode);
          ruleResourceLoadService.loadProjectPmmlRefData(projectCode);
        }
        dedfu.executeDrlContents(insertMap, vList, metaMap, ruleArgs[0]);
	
        ruleTestService.doRuleResultDoubleParse(insertMap, metaMap);
        DroolsRuleLog droolsRuleLog = dedfu.getDroolsRuleLog();
        insertMap.put("tracks",ruleTestService.getTrailMap(droolsRuleLog));
        Map<String, List> trailMap = ruleTestService.getTrailMap(droolsRuleLog);
        insertMap = dedfu.getDroolsRuleLog().getScoreTrailMap(insertMap);
        System.out.println("执行后的insertMap值为:"+insertMap);
        List<Map<String, Object>> list = droolsRuleLog.getLogs();
        for (Map<String, Object> map : list) {
            System.out.println(map.get("group") + ":" + map.get("name"));
        }
        if ("xml".equals(type)) {
           return RuleBomMapXmlConvert.bom2xml(insertMap, metaMap, true);
        } else {
            if("0".equals(bcm)){
                return RuleBomMapJsonConvert.bom2Json(insertMap, metaMap);
            }else{
                insertMap.put("DecisionFlowName",ruleArgs[0]);
                insertMap.put("ruleExecutResultList", list);
                return RuleMapAndJsonUtils.mapConverJson(insertMap,businessInputMap);
            }
        }
    }
    
    
    public String excuteDrl(RuleExecuteVO ruleExecute) throws Exception {

    	String xml = ruleExecute.getInputXml();
    	String code = ruleExecute.getCode();
    	String version = ruleExecute.getVersion();
    	String projectCode= ruleExecute.getProjectCode();
    	String modelType = ruleExecute.getModelType();
        Map<String, MClass> metaMap = dataBomService.findMapClass(projectCode);

        Map<String, Object> insertMap = null;
        //Map<String,Object> businessInputMap = JSON.parseObject(xml, Map.class);
        insertMap = RuleBomMapJsonConvert.json2bom(xml, metaMap);   

        List<RuleVersioninfo> vList = this.ruleFlowService.findRuleFlowPublishVersion(projectCode, code, version);
        ruleCodeblockService.addFuncInfo(vList);
        DroolsExcuteDrlUtils dedfu = new DroolsExcuteDrlUtils();
        dedfu.setProjectCode(projectCode);
        Map<String,String> funcMap  = new  HashMap<>();
        String  funcStr  =  this.ruleCodeblockService.getEffectiveFunc(projectCode);
        funcMap.put(projectCode,funcStr);
        dedfu.setFuncMap(funcMap);	
        dedfu.setDrlMap(this.ruleFlowService.findRuleRefeVerByProjectCode(projectCode));
        if (RuleModelTypeEnum.RuleFlow.code.equals(modelType)|| RuleModelTypeEnum.StrategyFlow.code.equals(modelType)) {
          ruleResourceLoadService.loadProjectPmml(projectCode);
          ruleResourceLoadService.loadProjectPmmlRefData(projectCode);
        }
    
        dedfu.executeDrlContents(insertMap, vList, metaMap,code);
	
        ruleTestService.doRuleResultDoubleParse(insertMap, metaMap);
        DroolsRuleLog droolsRuleLog = dedfu.getDroolsRuleLog();
        insertMap.put("tracks",ruleTestService.getTrailMap(droolsRuleLog));
        Map<String, List> trailMap = ruleTestService.getTrailMap(droolsRuleLog);
        insertMap = dedfu.getDroolsRuleLog().getScoreTrailMap(insertMap);
        System.out.println("执行后的insertMap值为:"+insertMap);
        List<Map<String, Object>> list = droolsRuleLog.getLogs();
        for (Map<String, Object> map : list) {
            System.out.println(map.get("group") + ":" + map.get("name"));
        }
  

        return RuleBomMapJsonConvert.bom2Json(insertMap, metaMap);
        
    }
    
    public RuleLogs excuteDrl(String xml, String ruleflowInfo, String projectCode) {
        if (StringUtils.isEmpty(ruleflowInfo)) {
            return null;
        }
        RuleLogs ruleLogs = new RuleLogs(UUID.randomUUID().toString(),projectCode,null,ruleflowInfo);
        long curr = System.currentTimeMillis();
        try {
	        Map<String, MClass> metaMap = dataBomService.findMapClass(projectCode);
	        Map<String, Object> insertMap = null;
	        insertMap = RuleBomMapJsonConvert.json2bom(xml, metaMap);
	        String[] ruleArgs = StringUtils.split(ruleflowInfo, "_");
	        List<RuleVersioninfo> vList = this.ruleFlowService.findRuleFlowPublishVersion(projectCode, ruleArgs[0], ruleArgs[1]);

	        ruleCodeblockService.addFuncInfo(vList);
	        DroolsExcuteDrlUtils dedfu = new DroolsExcuteDrlUtils();
	        dedfu.setDrlMap(this.ruleFlowService.findRuleRefeVerByProjectCode(projectCode));
	        dedfu.executeDrlContents(insertMap, vList, metaMap, ruleflowInfo);
	        ruleLogs.setLogs(dedfu.getDroolsRuleLog().getLogs());
	        ruleLogs.setIssuccess("1");
	        ruleLogs.setRuleParam(xml);
	        ruleLogs.setRuleResult(JSON.toJSONString(insertMap));
	        ruleLogs.setRunTime((System.currentTimeMillis()-curr)+"");
        }catch (Exception e) {
			// TODO: handle exception
		}
        return ruleLogs;
    }
    @Override
    public String excuteMath(String xml, String type, String projectCode) throws Exception {

        Map<String, MClass> metaMap = dataBomService.findMapClass(projectCode);

        Map<String, Object> dataMap = null;
        if ("xml".equals(type)) {
            dataMap = RuleBomMapXmlConvert.xml2bom(xml, metaMap);
        } else {
            dataMap = RuleBomMapJsonConvert.json2bom(xml, metaMap);
        }

        HashMap<String, Object> mathMap = new HashMap<String, Object>();

        Set<String> ckeys = metaMap.keySet();
        for (String mclassname : ckeys) {
            Map<String, MField> mfMap = metaMap.get(mclassname).getFieldMap();

            Set<String> fkeys = mfMap.keySet();
            for (String mfieldname : fkeys) {
                Object subDataMap = dataMap.get(mclassname);
                if (subDataMap != null) {
                    mathMap.put(mfMap.get(mfieldname).getId(), ((Map<String, Object>) subDataMap).get(mfieldname));

                }
            }
        }
        for (String mclassname : ckeys) {
            Map<String, MField> mfMap = metaMap.get(mclassname).getFieldMap();

            Set<String> fkeys = mfMap.keySet();
            for (String mfieldname : fkeys) {
                if ("true".equalsIgnoreCase(mfMap.get(mfieldname).getIsDerives())) {
                    System.out.println("math to result : " + mfieldname);
                    Object result = MathHelper.invokeMath(mathMap, mfMap.get(mfieldname).getMathStr());
                    ((Map<String, Object>) dataMap.get(mclassname)).put(mfieldname, result);


                }
            }
        }

        String resultxml = RuleBomMapXmlConvert.bom2xml(dataMap, metaMap, true);

        return resultxml;
    }

    @Override
    public String excuteRule(String xml, String ruleflowInfo, String type, String projectCode) throws Exception {
        return null;
    }


}
